package thread;

public class SyncDemo3 {
    public static void main(String[] args) {
        //new Thread(Foo::doSome).start();
        // new Thread(Foo::doSome).start();
        Foo f1 = new Foo();
        Foo f2 = new Foo();
        new Thread(() -> f1.doSome()).start();
        new Thread(() -> f2.doSome()).start();
    }
}

class Foo {
    /**
     * 如果doSome方法是成员方法:
     * public synchronized void doSome(){..}   那么此时synchronized指定的同步监视器对象为this
     * 因此如果两个线程调用时:
     * new Thread(()->f1.doSome()).start();    该线程看到的同步监视器为f1
     * new Thread(()->f2.doSome()).start();    该线程看到的同步监视器为f2
     * 由于两个线程看到的并非同一个对象,因此两个线程互不影响，可以一起执行
     * <p>
     * 如果doSome方法是静态方法:
     * public static synchronized void doSome(){..}
     * 那么此时synchronized指定的同步监视器对象为Foo.class  注:每个类仅有一个类对象(后面反射知识会讲)
     * 因此如果两个线程调用时:
     * new Thread(()->f1.doSome()).start();
     * new Thread(()->f2.doSome()).start();
     * 由于两个线程看到的同步监视器对象是同一个对象,因此两个线程互斥，只能一个线程执行
     */
    public static synchronized void doSome() {
        //静态方法中的同步块中指定同步监视器对象仍然可以用类对象
        synchronized (Foo.class) {
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + "正在执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(t.getName() + "执行完毕");
        }
    }
}